home *** CD-ROM | disk | FTP | other *** search
/ BBS Toolkit / BBS Toolkit.iso / maximus / valmsg19.zip / VALMSG.C next >
C/C++ Source or Header  |  1992-08-26  |  12KB  |  365 lines

  1. /*
  2.  
  3. VALMSG -- Creates validation messages from questionnaire data
  4.  
  5. Version 1.9  (8/26/92)
  6.  
  7. Written by Bob Quinlan of Austin, Texas, USA
  8. Sysop of Red October at 512-834-2593 (1:382/111)
  9.  
  10. Copyright 1992 by Bob Quinlan
  11.  
  12. Compatible with Maximus 2.00 and 2.01
  13.  
  14.  
  15. This program reads a single user's questionnaire data and generates a
  16. message from that user to the sysop containing the data.  You can change
  17. the defaults for who the message comes from, who the messages is
  18. addressed to, and what subject goes on the message.
  19.  
  20.     /Mmessagearea   Message area "number".  This must be supplied.
  21.  
  22.     /Vfile          Validation file.  This must be supplied.
  23.  
  24.     /Aareafile      Area file.  Default is AREA.DAT in the current
  25.                     directory.
  26.  
  27.     /Fusername      From username.  If this is not supplied the first
  28.                     line of the validation file will be assumed to be a
  29.                     [post] entry and the user's name will be extracted
  30.                     from it.
  31.  
  32.     /Ssubject       Subject line.  (default: Questionnaire)
  33.  
  34.     /Tusername      To username.   (default: Sysop)
  35.  
  36. You may want to supply multiple word values for /F, /S, and /T.  You can
  37. separate the words by spaces or by underscores (which will be replaced
  38. by spaces).  For example, both of these would produce the same results:
  39.  
  40.     valmsg /mper /vquest.tmp /tBob Quinlan /sHello there!
  41.  
  42.     valmsg /mper /vquest.tmp /tBob_Quinlan /sHello_there!
  43.  
  44.  
  45. There are any number of ways that VALMSG can be used.  I'll show you my
  46. questionnaire and part of my Maximus batch file as examples of one way.
  47.  
  48. Here is my questionnaire (somewhat edited for length) between the lines:
  49. -------------------------------------------------------------------------------
  50. [lightblue]Do you wish to fill out the questionnaire [[Y,n]? [green menu]yn|
  51. [choice]n[quit]
  52. [open]D:\Max\Quest.Tmp
  53. [post][lightblue]
  54. Enter your first and last name: [green ansreq clear_stacked readln]
  55. [lightblue]
  56. Enter your home phone number (including area code): [green readln]
  57.  
  58. [lightblue]Address (line 1 of 3): [green readln]
  59. [lightblue]Address (line 2 of 3): [green ansopt readln]
  60. [lightblue]Address (line 3 of 3): [green readln]
  61. [lightcyan][ansreq][open]Nul
  62. Thank you for filling out the questionnaire!
  63.  
  64. When you log off the system will automatically generate a message from
  65. you to the sysop containing your questionnaire answers.
  66.  
  67. [lightblue enter]
  68. -------------------------------------------------------------------------------
  69.  
  70. You could run VALMSG from a MECCA, but I like to run it after the user
  71. has logged off.  Here is the piece of my Maximus batch file that does
  72. the job:
  73.  
  74. if not exist quest.tmp goto noquest
  75.     valmsg /mper /vquest.tmp /tBob Quinlan
  76.     type quest.tmp >>quest.log
  77.     del quest.tmp
  78. :noquest
  79.  
  80. If QUEST.TMP exists VALMSG is run to process it.  Then the TYPE command
  81. appends QUEST.TMP onto the end of the permanent QUEST.LOG file and
  82. QUEST.TMP is deleted.
  83.  
  84.  
  85. VALMSG returns ERRORLEVEL 0 after a successful run.  ERRORLEVEL 1 is
  86. returned to indicate an error.
  87.  
  88. NOTICE:  You may use, copy, and distribute this program freely as long
  89. as you insure that both the executable and the documentation (.DOC)
  90. files are included in the distribution package.  The source code does
  91. not need to be included.  You may modify this program and document, so
  92. long as reasonable credit is given to the original author if a
  93. substantial portion of the original remains intact.  The author is not
  94. responsible for any losses which may occur either directly or indirectly
  95. as a result of using this program.
  96.  
  97. This program uses the Squish MsgAPI and the Maximus structures written
  98. by Scott J. Dudley.  "Squish" is a trademark of Scott J. Dudley.
  99.  
  100. HISTORY:
  101. Version 1.9   (8/26/92) -- Fixed a problem with handling multiple-word
  102.                            parameters.
  103. Version 1.8   (8/25/92) -- Added the ability to pass multiple-word
  104.                            parameters using spaces.
  105. Version 1.7   (8/10/92) -- Provided additional documentation and
  106.                            examples of how to use the program.  No
  107.                            code changes.
  108. Version 1.6   (6/03/92) -- Added *.MSG support.  /M is now the "number"
  109.                            for the area, not its path.  You may need to
  110.                            use the /A switch if AREA.DAT is not in the
  111.                            current directory.
  112. Version 1.5   (5/26/92) -- Use _fsopen instead of local s_fopen.
  113. Version 1.4   (5/13/92) -- Added file sharing.
  114. Version 1.3   (4/23/92) -- Zero-out headers.  Cleaned up docs.
  115. Version 1.2   (4/18/92) -- Extract username properly from data.
  116. Version 1.1   (4/17/92) -- Added switches.
  117. Version 1.0   (4/15/92) -- Original release.  Written in Borland C.
  118.  
  119. Large memory model
  120. */
  121.  
  122. #include <ctype.h>
  123. #include <dos.h>
  124. #include <errno.h>
  125. #include <fcntl.h>
  126. #include <io.h>
  127. #include <share.h>
  128. #include <stdio.h>
  129. #include <stdlib.h>
  130. #include <string.h>
  131. #include <sys\stat.h>
  132. #include <sys\types.h>
  133. #include <msgapi.h>     /*  From MsgAPI by Scott J. Dudley  */
  134. #include <prog.h>       /*  From MsgAPI by Scott J. Dudley  */
  135. #include <alc.h>        /*  From MsgAPI by Scott J. Dudley  */
  136. #include <mstruct1.h>   /*  Maximus structures by Scott J. Dudley: modified
  137.                             to avoid duplicate definitions of datestamps  */
  138.  
  139. #define MAXLINE     (128)
  140. #define MAXNAME     (36)
  141. #define BUFSIZE     (2048)
  142.  
  143.  
  144. int main(int argc, char *argv[])
  145. {
  146. struct _area arearef;
  147. XMSG   xmsg;
  148. MSG    *area;
  149. MSGH   *msg;
  150. UMSGID uid;
  151. char   ctrl[MAXLINE];
  152. char   buffer[BUFSIZE];
  153. long   textlen;
  154. dword  offset, msgn;
  155. int    t;
  156. int    ctrllen;
  157. struct _minf mi;
  158.  
  159. long   slen;
  160.  
  161. char   areaname[MAX_ALEN] = {""};
  162. char   areafile[MAXLINE] = {"AREA.DAT"};
  163. FILE   *areafile_fp;
  164. char   valfile[MAXLINE] = {""};
  165. FILE   *valfile_fp;
  166. char   msgpath[MAXLINE];
  167. FILE   *msgpath_fp;
  168.  
  169. struct date sysdate;
  170. struct time systime;
  171.  
  172. char   param = '\0';
  173.  
  174. char   line[MAXLINE];
  175. char   *ch;
  176. int    i;
  177.  
  178.  
  179. /************/
  180. /*  VALMSG  */
  181. /************/
  182.  
  183. printf("VALMSG 1.9 -- Copyright 1992 by Bob Quinlan (8/26/92)\n");
  184.  
  185. /*  Zero-out header  */
  186. memset(&xmsg, 0, sizeof(XMSG));
  187.  
  188. /*  Process switches  */
  189. *xmsg.from = '\0';
  190. *xmsg.subj = '\0';
  191. *xmsg.to = '\0';
  192. for (i=1; i<argc; i++)
  193.     {
  194.     /*  Convert previous param to uppercase so single-pass switches will
  195.         not recognize it more than once  */
  196.     param = toupper(param);
  197.     /*  If new parameter set it to lower case for first pass  */
  198.     if (argv[i][0] == '/')
  199.         param = tolower(argv[i][1]);
  200.     switch (param)
  201.         {
  202.         case 'a':  /*  AREA.DAT file  */
  203.             strncpy(areafile, argv[i]+2, MAXLINE);
  204.             break;
  205.         case 'F':  /*  From (sendar): append additional words  */
  206.             strncat(xmsg.from, " ", XMSG_FROM_SIZE);
  207.             /*  Fall through to next case!  */
  208.         case 'f':  /*  From (sender): defaults to sender's name  */
  209.             strncpy(xmsg.from, argv[i]+((islower(param) != 0)*2),
  210.                   XMSG_FROM_SIZE);
  211.             /*  Replace underscores with spaces  */
  212.             while ((ch = strchr(xmsg.from, '_')) != NULL)
  213.                 *ch = ' ';
  214.             break;
  215.         case 'm':  /*  Message area "number"  */
  216.             if (strlen(argv[i]+2) < MAX_ALEN)
  217.                 strcpy(areaname, argv[i]+2);
  218.             else
  219.                 {
  220.                 fprintf(stderr,
  221.                       "VALMSG: %s is too long to be an area \"number\"\n",
  222.                       argv[i]+2);
  223.                 exit(1);
  224.                 }
  225.             break;
  226.         case 'S':  /*  Subject: append additional words  */
  227.             strncat(xmsg.subj, " ", XMSG_SUBJ_SIZE);
  228.             /*  Fall through to next case!  */
  229.         case 's':  /*  Subject: defaults to "Questionnaire"  */
  230.             strncpy(xmsg.subj, argv[i]+((islower(param) != 0)*2), XMSG_SUBJ_SIZE);
  231.             /*  Replace underscores with spaces  */
  232.             while ((ch = strchr(xmsg.subj, '_')) != NULL)
  233.                 *ch = ' ';
  234.             break;
  235.         case 'T':  /*  To (receiver): append additional words  */
  236.             strncat(xmsg.to, " ", XMSG_TO_SIZE);
  237.             /*  Fall through to next case!  */
  238.         case 't':  /*  To (receiver): defaults to "Sysop"  */
  239.             strncat(xmsg.to, argv[i]+((islower(param) != 0)*2), XMSG_TO_SIZE);
  240.             /*  Replace underscores with spaces  */
  241.             while ((ch = strchr(xmsg.to, '_')) != NULL)
  242.                 *ch = ' ';
  243.             break;
  244.         case 'v':  /*  Validation file  */
  245.             strncpy(valfile, argv[i]+2, MAXLINE);
  246.             break;
  247.         default:
  248.             fprintf(stderr, "VALMSG: Unknown switch: %s\n", argv[i]);
  249.             break;
  250.         }
  251.     }
  252. if ((*valfile == '\0') || (*areaname == '\0'))
  253.     {
  254.     fprintf(stderr, "VALMSG: Must define /m and /v.\n");
  255.     exit(1);
  256.     }
  257.  
  258. /*  Open the area file  */
  259. if ((areafile_fp = _fsopen(areafile, "rb", SH_DENYNO)) == NULL)
  260.     {
  261.     fprintf(stderr, "VALMSG: Unable to open area file: %s\n", areafile);
  262.     exit(1);
  263.     }
  264.  
  265. /*  Read message area data from the area file  */
  266. fread(&arearef, sizeof(struct _area), 1, areafile_fp);
  267. slen = arearef.struct_len;
  268. *msgpath = '\0';
  269. i = 0;
  270. do
  271.     {
  272.     if (strcmpi(arearef.name, areaname) == 0)
  273.         {
  274.         strcpy(msgpath, arearef.msgpath);
  275.         break;
  276.         }
  277.     fseek(areafile_fp, (++i)*slen, SEEK_SET);
  278.     } while (fread(&arearef, sizeof(struct _area), 1, areafile_fp) > 0);
  279.  
  280. /*  Close the area file  */
  281. fclose(areafile_fp);
  282.  
  283. /*  If no message path was assigned...  */
  284. if (*msgpath == '\0')
  285.     {
  286.     fprintf(stderr, "VALMSG: %s is not a valid message area\n", areaname);
  287.     exit(1);
  288.     }
  289.  
  290. /*  Read validation data  */
  291. if ((valfile_fp = _fsopen(valfile, "rb", SH_DENYNO)) == NULL)
  292.     {
  293.     fprintf(stderr, "VALMSG: Unable to open validation file: %s\n", valfile);
  294.     exit(1);
  295.     }
  296. textlen = fread(&buffer, sizeof(char), BUFSIZE, valfile_fp);
  297. fclose(valfile_fp);
  298.  
  299. /*  Fill in the message header fields  */
  300.  
  301. if (*xmsg.from == '\0')
  302.     {
  303.     /*  Extract user's name from validation data  */
  304.     strncpy(xmsg.from, buffer+2, MAXNAME);
  305.     ch = strchr(xmsg.from, '\t');
  306.     if (ch != NULL)
  307.         *ch = '\0';
  308.     }
  309.  
  310. if (*xmsg.to == '\0')
  311.     strcpy(xmsg.to, "Sysop");
  312.  
  313. if (*xmsg.subj == '\0')
  314.     strcpy(xmsg.subj, "Questionnaire");
  315.  
  316. strcpy(ctrl, "\x1");
  317. ctrllen = strlen(ctrl);
  318.  
  319. xmsg.attr = MSGPRIVATE;
  320.  
  321. getdate(&sysdate);
  322. gettime(&systime);
  323. xmsg.date_written.date.yr = sysdate.da_year-1980;  /*  Note: date.yr = year-1980  */
  324. xmsg.date_written.date.mo = sysdate.da_mon;
  325. xmsg.date_written.date.da = sysdate.da_day;
  326. xmsg.date_written.time.hh = systime.ti_hour;
  327. xmsg.date_written.time.mm = systime.ti_min;
  328. xmsg.date_written.time.ss = systime.ti_sec;
  329.  
  330. xmsg.date_arrived = xmsg.date_written;
  331.  
  332. /*  Open the message API  */
  333. t = arearef.type;
  334. mi.def_zone = 1;
  335. MsgOpenApi(&mi);
  336.  
  337. /*  Open the message area  */
  338. if ((area=MsgOpenArea(msgpath, MSGAREA_CRIFNEC, t)) == NULL)
  339.     {
  340.     fprintf(stderr, "VALMSG: Unable to open %s!\n", msgpath);
  341.     exit(1);
  342.     }
  343.  
  344. /*  Write the user message  */
  345. MsgLock(area);
  346. if ((msg=MsgOpenMsg(area, MOPEN_CREATE, 0L)) == NULL)
  347.     {
  348.     fprintf(stderr, "VALMSG: Unable to write to ouptut area.  msg#%ld\n", msgn);
  349.     exit(1);
  350.     }
  351. MsgWriteMsg(msg, FALSE, &xmsg, buffer, textlen, textlen, ctrllen, ctrl);
  352. MsgCloseMsg(msg);
  353. MsgUnlock(area);
  354.  
  355. /*  Close the message area  */
  356. MsgCloseArea(area);
  357.  
  358. /*  Close the message API  */
  359. MsgCloseApi();
  360.  
  361. return 0;
  362. }
  363.  
  364.  
  365.